/*
 * Copyright 2019-2024 NXP
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/************************************************************************************
 * Include
 ************************************************************************************/

#include <stdint.h>
#include "board_platform.h"
#include "fsl_common.h"
#include "clock_config.h"
#include "pin_mux.h"
#include "board.h"
#include "app.h"
#include "fsl_port.h"
#include "fsl_lpuart.h"
#include "fsl_adapter_gpio.h"
#include "phOsalUwb.h"
//#include "tml.h"
#include "fsl_wuu.h"
#include "fwk_platform_ble.h"
#include "FunctionLib.h"
#include "fsl_debug_console.h"
#if !(defined BOARD_DEBUG_UART_INSTANCE) || (BOARD_DEBUG_UART_INSTANCE > 1)
#error "Must define a valid UART for console to work"
#endif

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/************************************************************************************
 * Private memory declarations
 ************************************************************************************/

/************************************************************************************
*************************************************************************************
* Private type definitions and macros
*************************************************************************************
************************************************************************************/

/************************************************************************************
*************************************************************************************
* Private functions
*************************************************************************************
************************************************************************************/

static void BOARD_InitPinsDebugConsole(void)
{
#if (BOARD_DEBUG_UART_INSTANCE == 1U)
#if !defined(DBG_CONSOLE_RX_DISABLE) || (DBG_CONSOLE_RX_DISABLE == 0)
    BOARD_InitPinLPUART1_RX();
#endif
#if !defined(DBG_CONSOLE_TX_DISABLE) || (DBG_CONSOLE_TX_DISABLE == 0)
    BOARD_InitPinLPUART1_TX();
#endif
#elif (BOARD_DEBUG_UART_INSTANCE == 0U)
#if !defined(DBG_CONSOLE_RX_DISABLE) || (DBG_CONSOLE_RX_DISABLE == 0)
    BOARD_InitPinLPUART0_RX();
#endif
#if !defined(DBG_CONSOLE_TX_DISABLE) || (DBG_CONSOLE_TX_DISABLE == 0)
    BOARD_InitPinLPUART0_TX();
#endif
#else
#error Only LPUART0 or LPUART1 supported
#endif
}

static void BOARD_UninitPinsDebugConsole(void)
{
#if (BOARD_DEBUG_UART_INSTANCE == 1U)
#if !defined(DBG_CONSOLE_RX_DISABLE) || (DBG_CONSOLE_RX_DISABLE == 0)
    BOARD_UnInitPinLPUART1_RX();
#endif
#if !defined(DBG_CONSOLE_TX_DISABLE) || (DBG_CONSOLE_TX_DISABLE == 0)
    BOARD_UnInitPinLPUART1_TX();
#endif
#elif (BOARD_DEBUG_UART_INSTANCE == 0U)
#if !defined(DBG_CONSOLE_RX_DISABLE) || (DBG_CONSOLE_RX_DISABLE == 0)
    BOARD_UnInitPinLPUART0_RX();
#endif
#if !defined(DBG_CONSOLE_TX_DISABLE) || (DBG_CONSOLE_TX_DISABLE == 0)
    BOARD_UnInitPinLPUART0_TX();
#endif
#else
#error Only LPUART0 or LPUART1 supported
#endif
}

static void BOARD_InitPinsAppConsole(void)
{
#if (BOARD_APP_UART_INSTANCE == 1U)
    BOARD_InitPinLPUART1_RX();
    BOARD_InitPinLPUART1_TX();
#elif (BOARD_APP_UART_INSTANCE == 0U)
    BOARD_InitPinLPUART0_RX();
    BOARD_InitPinLPUART0_TX();
#if (defined(gBoardUseUart0HwFlowControl) && (gBoardUseUart0HwFlowControl > 0))
    BOARD_InitPinLPUART0_RTS();
    BOARD_InitPinLPUART0_CTS();
#endif
#else
#error Only LPUART0 or LPUART1 supported
#endif
}

static void BOARD_UninitPinsAppConsole(void)
{
#if (BOARD_APP_UART_INSTANCE == 1U)
    BOARD_UnInitPinLPUART1_RX();
    BOARD_UnInitPinLPUART1_TX();
#elif (BOARD_APP_UART_INSTANCE == 0U)
    BOARD_UnInitPinLPUART0_RX();
    BOARD_UnInitPinLPUART0_TX();
#if (defined(gBoardUseUart0HwFlowControl) && (gBoardUseUart0HwFlowControl > 0))
    BOARD_UnInitPinLPUART0_RTS();
    BOARD_UnInitPinLPUART0_CTS();
#endif
#else
#error Only LPUART0 or LPUART1 supported
#endif
}

static void BOARD_InitPinsApp2Console(void)
{
#if (BOARD_APP2_UART_INSTANCE == 1U)
    BOARD_InitPinLPUART1_RX();
    BOARD_InitPinLPUART1_TX();
#elif (BOARD_APP2_UART_INSTANCE == 0U)
    BOARD_InitPinLPUART0_RX();
    BOARD_InitPinLPUART0_TX();
#if (defined(gBoardUseUart0HwFlowControl) && (gBoardUseUart0HwFlowControl > 0))
    BOARD_InitPinLPUART0_RTS();
    BOARD_InitPinLPUART0_CTS();
#endif
#else
#error Only LPUART0 or LPUART1 supported
#endif
}

static void BOARD_UninitPinsApp2Console(void)
{
#if (BOARD_APP2_UART_INSTANCE == 1U)
    BOARD_UnInitPinLPUART1_RX();
    BOARD_UnInitPinLPUART1_TX();
#elif (BOARD_APP2_UART_INSTANCE == 0U)
    BOARD_UnInitPinLPUART0_RX();
    BOARD_UnInitPinLPUART0_TX();
#if (defined(gBoardUseUart0HwFlowControl) && (gBoardUseUart0HwFlowControl > 0))
    BOARD_UnInitPinLPUART0_RTS();
    BOARD_UnInitPinLPUART0_CTS();
#endif
#else
#error Only LPUART0 or LPUART1 supported
#endif
}

/************************************************************************************
*************************************************************************************
* Public functions
*************************************************************************************
************************************************************************************/
void BOARD_InitAppConsole(void)
{
    /* set clock */
    CLOCK_SetIpSrc(BOARD_APP_UART_CLK, BOARD_APP_UART_CLKSRC);
    /* enable clock with kCLOCK_IpClkControl_fun3 or kCLOCK_IpClkControl_fun2 to
     * keep wake up capability in low power (domain in sleep) */
    CLOCK_EnableClockLPMode(BOARD_APP_UART_CLK, kCLOCK_IpClkControl_fun3);

    /* init lpuart pins */
    BOARD_InitPinsAppConsole();
}

bool BOARD_IsAppConsoleBusy(void)
{
    return ((((uint32_t)kLPUART_TransmissionCompleteFlag) &
             LPUART_GetStatusFlags((LPUART_Type *)BOARD_APP_UART_BASEADDR)) == 0U);
}

void BOARD_UninitAppConsole(void)
{
    /* Wait for app console output finished. */
    while (BOARD_IsAppConsoleBusy() == true)
    {
        ;
    }
    BOARD_UninitPinsAppConsole();
    CLOCK_DisableClock(BOARD_APP_UART_CLK);
}

/* Initialize debug console. */
void BOARD_InitDebugConsole(void)
{
    uint32_t uartClkSrcFreq;
    status_t status;

    CLOCK_SetIpSrc(BOARD_DEBUG_UART_CLK, BOARD_DEBUG_UART_CLKSRC);
    CLOCK_EnableClockLPMode(BOARD_DEBUG_UART_CLK, kCLOCK_IpClkControl_fun3);

    /* Set the pins for the Debug Console */
    BOARD_InitPinsDebugConsole();

    uartClkSrcFreq = BOARD_DEBUG_UART_CLK_FREQ;
    status =
        DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE, uartClkSrcFreq);
    assert(status == kStatus_Success);
    (void)status;
}

bool BOARD_IsDebugConsoleBusy(void)
{
    return ((((uint32_t)kLPUART_TransmissionCompleteFlag) &
             LPUART_GetStatusFlags((LPUART_Type *)BOARD_DEBUG_UART_BASEADDR)) == 0U);
}

void BOARD_UninitDebugConsole(void)
{
    /* Wait for debug console output finished. */
    while (BOARD_IsDebugConsoleBusy() == true)
    {
        ;
    }

    BOARD_UninitPinsDebugConsole();
    CLOCK_DisableClock(BOARD_DEBUG_UART_CLK);
}

void BOARD_ReinitDebugConsole(void)
{
    status_t status;

    CLOCK_SetIpSrc(BOARD_DEBUG_UART_CLK, BOARD_DEBUG_UART_CLKSRC);

    /* Set the pins for the Debug Console using UART0 */
    BOARD_InitPinsDebugConsole();
    CLOCK_EnableClockLPMode(BOARD_DEBUG_UART_CLK, kCLOCK_IpClkControl_fun3);

    /* we should normaly only need to reenable the clock by CLOCK_EnableClock(kCLOCK_Lpuart0);
      but on wakeup from deep sleep, the UART peripheral needs to be reinitialized
      Call DbgConsole_ExitLowpower() for debug console low power support, should not call DbgConsole_Deinit */
    status = DbgConsole_ExitLowpower();
    assert(status == kStatus_Success);
    (void)status;
}

void BOARD_InitApp2Console(void)
{
    /* set clock */
    CLOCK_SetIpSrc(BOARD_APP2_UART_CLK, BOARD_APP2_UART_CLKSRC);
    /* enable clock with kCLOCK_IpClkControl_fun3 or kCLOCK_IpClkControl_fun2 to
     * keep wake up capability in low power (domain in sleep) */
    CLOCK_EnableClockLPMode(BOARD_APP2_UART_CLK, kCLOCK_IpClkControl_fun3);

    /* init lpuart pins */
    BOARD_InitPinsApp2Console();
}

bool BOARD_IsApp2ConsoleBusy(void)
{
    return ((((uint32_t)kLPUART_TransmissionCompleteFlag) &
             LPUART_GetStatusFlags((LPUART_Type *)BOARD_APP2_UART_BASEADDR)) == 0U);
}

void BOARD_UninitApp2Console(void)
{
    /* Wait for app console output finished. */
    while (BOARD_IsApp2ConsoleBusy() == true)
    {
        ;
    }
    BOARD_UninitPinsApp2Console();
    CLOCK_DisableClock(BOARD_APP2_UART_CLK);
}

void BOARD_InitI2C1_SecureElement(void) {

    /* I2C for SE init */
    CLOCK_SetIpSrc(kCLOCK_Lpi2c1, kCLOCK_IpSrcFro192M);
    CLOCK_SetIpSrcDiv(kCLOCK_Lpi2c1, kSCG_SysClkDivBy16);
}

void BOARD_InitPins(void)
{
    BOARD_InitUWBPins();
    BOARD_UWBChipEnable();
    BOARD_InitUwbIRQ();
    BOARD_InitNFCPins();
    BOARD_NFCChipEnable();
    BOARD_InitNfcIRQ();
#ifdef K32W1480
    /*low power workaround only for K32W148 EVK*/
    BOARD_InitPinButtonBootConfig();
#endif
    BOARD_InitI2C1_SecureElement();


}

void BOARD_GetMCUUid(uint8_t *aOutUid16B, uint8_t *pOutLen)
{
    uint8_t mac_id[6] = {0};
    PLATFORM_GetBDAddr(mac_id);
    *pOutLen = 6;
    FLib_MemCpy(aOutUid16B, mac_id, 6);
}

void BOARD0_InitPins(void)
{
    /* Clock Configuration: Peripheral clocks are enabled; module does not stall low power mode entry */
    CLOCK_EnableClock(kCLOCK_PortA);

    const port_pin_config_t porta16_pin11_config = {/* Internal pull-up/down resistor is disabled */
                                                   (uint16_t)kPORT_PullDisable,
                                                   /* Low internal pull resistor value is selected. */
                                                   (uint16_t)kPORT_LowPullResistor,
                                                   /* Fast slew rate is configured */
                                                   (uint16_t)kPORT_FastSlewRate,
                                                   /* Passive input filter is disabled */
                                                   (uint16_t)kPORT_PassiveFilterDisable,
                                                   /* Open drain output is disabled */
                                                   (uint16_t)kPORT_OpenDrainDisable,
                                                   /* Low drive strength is configured */
                                                   (uint16_t)kPORT_LowDriveStrength,
                                                   /* Normal drive strength is configured */
                                                   (uint16_t)kPORT_NormalDriveStrength,
                                                   /* Pin is configured as LPUART0_RX */
                                                   (uint16_t)kPORT_MuxAlt6,
                                                   /* Pin Control Register fields [15:0] are not locked */
                                                   (uint16_t)kPORT_UnlockRegister};
    /* PORTA16 (pin 11) is configured as LPUART0_RX */
    PORT_SetPinConfig(PORTA, 16U, &porta16_pin11_config);

    const port_pin_config_t porta17_pin12_config = {/* Internal pull-up/down resistor is disabled */
                                                   (uint16_t)kPORT_PullDisable,
                                                   /* Low internal pull resistor value is selected. */
                                                   (uint16_t)kPORT_LowPullResistor,
                                                   /* Fast slew rate is configured */
                                                   (uint16_t)kPORT_FastSlewRate,
                                                   /* Passive input filter is disabled */
                                                   (uint16_t)kPORT_PassiveFilterDisable,
                                                   /* Open drain output is disabled */
                                                   (uint16_t)kPORT_OpenDrainDisable,
                                                   /* Low drive strength is configured */
                                                   (uint16_t)kPORT_LowDriveStrength,
                                                   /* Normal drive strength is configured */
                                                   (uint16_t)kPORT_NormalDriveStrength,
                                                   /* Pin is configured as LPUART0_TX */
                                                   (uint16_t)kPORT_MuxAlt6,
                                                   /* Pin Control Register fields [15:0] are not locked */
                                                   (uint16_t)kPORT_UnlockRegister};
    /* PORTA17 (pin 12) is configured as LPUART0_TX */
    PORT_SetPinConfig(PORTA, 17U, &porta17_pin12_config);
}

void BOARD0_InitDebugConsole(void)
{
    uint32_t uartClkSrcFreq = 0U;

    CLOCK_SetIpSrc(kCLOCK_Lpuart0, kCLOCK_IpSrcFro192M);
    uartClkSrcFreq = CLOCK_GetIpFreq(kCLOCK_Lpuart0);

    DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE, uartClkSrcFreq);
}


void GPIO_Init()
{
    /* Clock Configuration: Peripheral clocks are enabled; module does not stall low power mode entry */
    CLOCK_EnableClock(kCLOCK_GpioA);
    /* Clock Configuration: Peripheral clocks are enabled; module does not stall low power mode entry */
    CLOCK_EnableClock(kCLOCK_PortA);
    /* Clock Configuration: Peripheral clocks are enabled; module does not stall low power mode entry */
    CLOCK_EnableClock(kCLOCK_GpioB);
    /* Clock Configuration: Peripheral clocks are enabled; module does not stall low power mode entry */
    CLOCK_EnableClock(kCLOCK_PortB);
    gpio_pin_config_t io_config = {
        kGPIO_DigitalOutput,
        0,
    };
    /* Init output LED GPIO. */
    GPIO_PinInit(WAK15_GPIO, GPIO_PIN_WAK15, &io_config);
    GPIO_PinInit(WAK4_GPIO, GPIO_PIN_WAK4, &io_config);

    const port_pin_config_t WAK4_15 = {/* Internal pull-up/down resistor is disabled */
                                         (uint16_t)kPORT_PullDisable,
                                         /* Low internal pull resistor value is selected. */
                                         (uint16_t)kPORT_LowPullResistor,
                                         /* Fast slew rate is configured */
                                         (uint16_t)kPORT_FastSlewRate,
                                         /* Passive input filter is disabled */
                                         (uint16_t)kPORT_PassiveFilterDisable,
                                         /* Open drain output is disabled */
                                         (uint16_t)kPORT_OpenDrainDisable,
                                         /* Low drive strength is configured */
                                         (uint16_t)kPORT_LowDriveStrength,
                                         /* Normal drive strength is configured */
                                         (uint16_t)kPORT_NormalDriveStrength,
                                         /* Pin is configured as PTA19 PTB4*/
                                         (uint16_t)kPORT_MuxAsGpio,
                                         /* Pin Control Register fields [15:0] are not locked */
                                         (uint16_t)kPORT_UnlockRegister};

    PORT_SetPinConfig(WAK4_PORT, GPIO_PIN_WAK4, &WAK4_15);
    PORT_SetPinConfig(WAK15_PORT, GPIO_PIN_WAK15, &WAK4_15);


}

void GPIO_INPUT_LOW()
{
    /* 使能相关外设时钟 */
    CLOCK_EnableClock(kCLOCK_GpioA);
    CLOCK_EnableClock(kCLOCK_PortA);
    CLOCK_EnableClock(kCLOCK_GpioB);
    CLOCK_EnableClock(kCLOCK_PortB);
    CLOCK_EnableClock(kCLOCK_GpioC);
    CLOCK_EnableClock(kCLOCK_PortC);

    // GPIO配置：保持数字输入模式
    gpio_pin_config_t io_config = {
        kGPIO_DigitalInput,  // 输入模式
        0,                   // 输入模式下此值无效
    };

    /* 初始化输入GPIO */
    GPIO_PinInit(WAK15_GPIO, GPIO_PIN_WAK15, &io_config);
    GPIO_PinInit(WAK4_GPIO, GPIO_PIN_WAK4, &io_config);
    GPIO_PinInit(GPIOB,5u,&io_config);
    GPIO_PinInit(GPIOA,0u,&io_config);
    GPIO_PinInit(GPIOA,1u,&io_config);
    GPIO_PinInit(GPIOA,18u,&io_config);
    GPIO_PinInit(GPIOA,20u,&io_config);
    GPIO_PinInit(GPIOA,21u,&io_config);
    GPIO_PinInit(GPIOD,1u,&io_config);
    GPIO_PinInit(GPIOD,2u,&io_config);
    GPIO_PinInit(GPIOD,3u,&io_config);
    GPIO_PinInit(GPIOC,6u,&io_config);
    GPIO_PinInit(GPIOC,7u,&io_config);

    // Port配置：核心修改为启用下拉电阻
    const port_pin_config_t WAK4_15 = {
        (uint16_t)kPORT_PullDown,          // 启用内部下拉电阻（关键修改）
        (uint16_t)kPORT_FastSlewRate,      // 输入模式下可保留默认
        (uint16_t)kPORT_PassiveFilterDisable,
        (uint16_t)kPORT_OpenDrainDisable,  // 输入模式下无效
        (uint16_t)kPORT_MuxAsGpio,         // 复用为GPIO功能
        (uint16_t)kPORT_UnlockRegister
    };

    /* 应用Port配置 */
    PORT_SetPinConfig(WAK4_PORT, GPIO_PIN_WAK4, &WAK4_15);
    PORT_SetPinConfig(WAK15_PORT, GPIO_PIN_WAK15, &WAK4_15);
    PORT_SetPinConfig(PORTB,5u,&WAK4_15);
    PORT_SetPinConfig(PORTA,0u,&WAK4_15);
    PORT_SetPinConfig(PORTA,1u,&WAK4_15);
    PORT_SetPinConfig(PORTA,18u,&WAK4_15);
    PORT_SetPinConfig(PORTA,20u,&WAK4_15);
    PORT_SetPinConfig(PORTA,21u,&WAK4_15);
    PORT_SetPinConfig(PORTD,1u,&WAK4_15);
    PORT_SetPinConfig(PORTD,2u,&WAK4_15);
    PORT_SetPinConfig(PORTD,3u,&WAK4_15);
    PORT_SetPinConfig(PORTC,6u,&WAK4_15);
    PORT_SetPinConfig(PORTC,7u,&WAK4_15);

}
/*******************************************************************************
 * EOF
 ******************************************************************************/
